/**
* http://www.informit.com/guides/content.asp?g=java&seqNum=58
*/
package com.informit.guides;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import javax.swing.JList;
import net.java.dev.spellcast.utilities.LockableListModel;
public class JDnDList
extends JList
implements DragSourceListener, DragGestureListener, DropTargetListener
{
private boolean acceptsDrops;
private int overIndex;
private final DragSource dragSource;
public JDnDList( final LockableListModel model )
{
this( model, true );
}
public JDnDList( final LockableListModel model, final boolean acceptsDrops )
{
super( model );
this.acceptsDrops = acceptsDrops;
this.setPrototypeCellValue( "1234567890" );
this.addKeyListener( new DeleteListener() );
// Configure ourselves to be a drag source
this.dragSource = new DragSource();
this.dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_MOVE, this );
// Configure ourselves to be a drop target
new DropTarget( this, this );
}
private class DeleteListener
extends KeyAdapter
{
@Override
public void keyPressed( final KeyEvent e )
{
if ( e.getKeyCode() != KeyEvent.VK_BACK_SPACE && e.getKeyCode() != KeyEvent.VK_DELETE )
{
return;
}
LockableListModel model = (LockableListModel) JDnDList.this.getModel();
Object[] selectedObjects = JDnDList.this.getSelectedValues();
for ( int i = 0; i < selectedObjects.length; ++i )
{
model.remove( selectedObjects[ i ] );
}
}
}
public void dragGestureRecognized( final DragGestureEvent dge )
{
Object[] selectedObjects = this.getSelectedValues();
if ( selectedObjects.length == 0 )
{
return;
}
StringBuffer sb = new StringBuffer();
for ( int i = 0; i < selectedObjects.length; i++ )
{
sb.append( selectedObjects[ i ].toString() + "\n" );
}
// Build a StringSelection object that the Drag Source
// can use to transport a string to the Drop Target
StringSelection text = new StringSelection( sb.toString() );
// Start dragging the object
this.dragSource.startDrag( dge, DragSource.DefaultMoveDrop, text, this );
}
public void dragDropEnd( final DragSourceDropEvent dsde )
{
}
public void dragExit( final DragSourceEvent dte )
{
this.overIndex = -1;
}
public void dragExit( final DropTargetEvent dte )
{
this.overIndex = -1;
}
public void dragEnter( final DragSourceDragEvent dsde )
{
this.overIndex = this.locationToIndex( dsde.getLocation() );
}
public void dragEnter( final DropTargetDragEvent dtde )
{
this.overIndex = this.locationToIndex( dtde.getLocation() );
}
public void dragOver( final DragSourceDragEvent dsde )
{
// See who we are over...
int overIndex = this.locationToIndex( dsde.getLocation() );
if ( overIndex != -1 && overIndex != this.overIndex )
{
// If the value has changed from what we were previously over
// then change the selected object to the one we are over; this
// is a visual representation that this is where the drop will occur
this.overIndex = overIndex;
}
}
public void dragOver( final DropTargetDragEvent dtde )
{
// See who we are over...
int overIndex = this.locationToIndex( dtde.getLocation() );
if ( overIndex != -1 )
{
// If the value has changed from what we were previously over
// then change the selected object to the one we are over; this
// is a visual representation that this is where the drop will occur
this.overIndex = overIndex;
}
}
public void drop( final DropTargetDropEvent dtde )
{
if ( !this.acceptsDrops )
{
return;
}
try
{
Transferable transferable = dtde.getTransferable();
if ( !transferable.isDataFlavorSupported( DataFlavor.stringFlavor ) )
{
dtde.rejectDrop();
return;
}
dtde.acceptDrop( DnDConstants.ACTION_MOVE );
// Find out where the item was dropped
int newIndex = Math.max( 0, this.locationToIndex( dtde.getLocation() ) );
// Get the items out of the transferable object and build an
// array out of them...
String s = (String) transferable.getTransferData( DataFlavor.stringFlavor );
String[] items = s.split( "\n" );
LockableListModel destination = (LockableListModel) this.getModel();
// If we are dragging onto ourself, move the items,
// otherwise just add them...
for ( int i = 0; i < items.length; ++i )
{
destination.remove( items[ i ] );
}
for ( int i = 0; i < items.length; ++i )
{
destination.add( newIndex + i, items[ i ] );
}
// Reset the over index
this.overIndex = -1;
dtde.getDropTargetContext().dropComplete( true );
}
catch ( IOException exception )
{
exception.printStackTrace();
System.err.println( "Exception" + exception.getMessage() );
dtde.rejectDrop();
}
catch ( UnsupportedFlavorException ufException )
{
ufException.printStackTrace();
System.err.println( "Exception" + ufException.getMessage() );
dtde.rejectDrop();
}
}
public void dropActionChanged( final DragSourceDragEvent e )
{
}
public void dropActionChanged( final DropTargetDragEvent e )
{
}
}